package cn.yx.common.core.util;

import cn.hutool.core.util.StrUtil;
import cn.yx.common.core.constant.SeparatorConstant;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * <p>字符串工具类</p>
 *
 * @author Wgssmart
 */
public final class StringUtil {

    public static final String EMPTY_STRING = "";
    public static final Pattern UNDERLINE_PATTERN = Pattern.compile("_(\\w)");
    public static final Pattern HYPHEN_PATTERN = Pattern.compile("-(\\w)");
    public static final Pattern CAMEL_PATTERN = Pattern.compile("[A-Z]");

    public static final String CHARACTERS = "(\\W)";

    private StringUtil() {
    }

    /**
     * 下划线转驼峰式
     *
     * @param value 带下划线的名称
     * @return
     */
    public static String underlineToCamel(String value) {
        return toCamel(value, SeparatorConstant.UNDERLINE, null);
    }

    /**
     * 带分割符的字符串转驼峰式，可指定去除前缀
     *
     * @param value      字符串，可带分割符
     * @param separator  指定的分割符
     * @param dropPrefix 去除前缀
     * @return
     */
    public static String toCamel(String value, String separator, String dropPrefix) {
        String newValue = StrUtil.isNotEmpty(dropPrefix) ? value.replace(dropPrefix, EMPTY_STRING).toLowerCase() : value.toLowerCase();
        Matcher matcher;
        if (SeparatorConstant.UNDERLINE.equals(separator)) {
            matcher = UNDERLINE_PATTERN.matcher(newValue);
        } else if (SeparatorConstant.HYPHEN.equals(separator)) {
            matcher = HYPHEN_PATTERN.matcher(newValue);
        } else {
            matcher = Pattern.compile(separator + CHARACTERS).matcher(newValue);
        }
        StringBuilder sb = new StringBuilder();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 驼峰式转下划线
     *
     * @param value
     * @return
     */
    public static String camelToUnderline(String value) {
        return camelToSeparator(value, SeparatorConstant.UNDERLINE, null);
    }

    /**
     * 驼峰式转带分割符的字符串，可指定添加前缀
     *
     * @param value     驼峰式字符串
     * @param separator 指定的分割符
     * @param addPrefix 添加前缀
     * @return
     */
    public static String camelToSeparator(String value, String separator, String addPrefix) {
        Matcher matcher = CAMEL_PATTERN.matcher(value);
        StringBuilder sb = new StringBuilder();
        while (matcher.find()) {
            matcher.appendReplacement(sb, separator + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        String returnStr = sb.toString();
        if (returnStr.startsWith(separator)) {
            returnStr = returnStr.substring(separator.length());
        }
        return StrUtil.isNotEmpty(addPrefix) ? addPrefix + returnStr : returnStr;
    }

    /**
     * 字符串转字符List，指定分割符
     *
     * @param value     字符串
     * @param separator 分割符
     * @return
     */
    public static List<String> stringList(String value, String separator) {
        return stringList(value.split(separator));
    }

    /**
     * 字符串数组转字符串List
     *
     * @param strArray 字符串数组
     * @return
     */
    public static List<String> stringList(String[] strArray) {
        return Arrays.stream(strArray).collect(Collectors.toList());
    }

    /**
     * 字符串转Integer List，指定分割符
     *
     * @param value     字符串
     * @param separator 分割符
     * @return
     */
    public static List<Integer> integerList(String value, String separator) {
        return integerList(value.split(separator));
    }

    /**
     * 字符串数组转化为Integer List
     *
     * @param strArray
     * @return
     */
    public static List<Integer> integerList(String[] strArray) {
        return Arrays.stream(strArray).map(Integer::valueOf).collect(Collectors.toList());
    }

    /**
     * 字符串转Long List，指定分割符
     *
     * @param value     字符串
     * @param separator 分割符
     * @return
     */
    public static List<Long> longList(String value, String separator) {
        return longList(value.split(separator));
    }

    /**
     * 字符串数组转化为Long List
     *
     * @param strArray
     * @return
     */
    public static List<Long> longList(String[] strArray) {
        return Arrays.stream(strArray).map(Long::valueOf).collect(Collectors.toList());
    }

    /**
     * 字符串转Double List，指定分割符
     *
     * @param value     字符串
     * @param separator 分割符
     * @return
     */
    public static List<Double> doubleList(String value, String separator) {
        return doubleList(value.split(separator));
    }

    /**
     * 字符串数组转化为Double List
     *
     * @param strArray
     * @return
     */
    public static List<Double> doubleList(String[] strArray) {
        return Arrays.stream(strArray).map(Double::valueOf).collect(Collectors.toList());
    }

    /**
     * 字符串转BigDecimal List，指定分割符
     *
     * @param value     字符串
     * @param separator 分割符
     * @return
     */
    public static List<BigDecimal> bigDecimalList(String value, String separator) {
        return bigDecimalList(value.split(separator));
    }

    /**
     * 字符串数组转化为BigDecimal List
     *
     * @param strArray
     * @return
     */
    public static List<BigDecimal> bigDecimalList(String[] strArray) {
        return Arrays.stream(strArray).map(BigDecimal::new).collect(Collectors.toList());
    }

    /**
     * 字符串转化为int数组
     *
     * @param value
     * @param separator
     * @return
     */
    public static int[] intArray(String value, String separator) {
        return intArray(value.split(separator));
    }

    /**
     * 字符串数组转化为int数组
     *
     * @param strArray
     * @return
     */
    public static int[] intArray(String[] strArray) {
        return Arrays.stream(strArray).mapToInt(Integer::parseInt).toArray();
    }

    /**
     * 字符串转化为long数组
     *
     * @param value
     * @param separator
     * @return
     */
    public static long[] longArray(String value, String separator) {
        return longArray(value.split(separator));
    }

    /**
     * 字符串数组转化为long数组
     *
     * @param strArray
     * @return
     */
    public static long[] longArray(String[] strArray) {
        return Arrays.stream(strArray).mapToLong(Long::parseLong).toArray();
    }

    /**
     * 字符串转化为double数组
     *
     * @param value
     * @param separator
     * @return
     */
    public static double[] doubleArray(String value, String separator) {
        return doubleArray(value.split(separator));
    }

    /**
     * 字符串数组转化为double数组
     *
     * @param strArray
     * @return
     */
    public static double[] doubleArray(String[] strArray) {
        return Arrays.stream(strArray).mapToDouble(Double::parseDouble).toArray();
    }

    /**
     * 字符串转化为BigDecimal数组
     *
     * @param value
     * @param separator
     * @return
     */
    public static BigDecimal[] bigDecimalArray(String value, String separator) {
        return bigDecimalArray(value.split(separator));
    }

    /**
     * 字符串数组转化为BigDecimal数组
     *
     * @param strArray
     * @return
     */
    public static BigDecimal[] bigDecimalArray(String[] strArray) {
        return Arrays.stream(strArray).map(BigDecimal::new).toArray(BigDecimal[]::new);
    }

    /**
     * 可在字符串不满足指定长度的情况下，用指定的前缀字符串补足长度
     *
     * @param value      字符串
     * @param length     字符串需要达到的长度
     * @param prefixChar 前缀字符串
     * @return 补足前缀字符后的字符中，如字符串"123"，指定长度为5，prefixChar为"0"，则返回字符串"00123"
     */
    public static String addPrefix(String value, int length, String prefixChar) {
        int len = value.length();
        if (len >= length) {
            return value;
        }
        StringBuilder prefixStr = new StringBuilder();
        for (int i = 0, lenDiff = length - len; i < lenDiff; i++) {
            prefixStr.append(prefixChar);
        }
        return prefixStr.append(value).toString();
    }

    /**
     * 可在字符串不满足指定长度的情况下，用前缀0补足长度
     *
     * @param value  字符串
     * @param length 字符串需要达到的长度
     * @return 补足前缀字符后的字符中，如字符串"123"，指定长度为5，则返回字符串"00123"
     */
    public static String addZeroPrefix(String value, int length) {
        return addPrefix(value, length, "0");
    }

}
